package com.caishi.lkx.exam.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.caishi.lkx.exam.mapper.NoteMapper;
import com.caishi.lkx.exam.model.*;
import com.caishi.lkx.exam.service.*;
import com.caishi.lkx.exam.vo.QuestionVo;
import com.zzw.common.Wrappers;
import com.zzw.common.entity.IBaseMapper;
import com.caishi.lkx.exam.ienum.type.PaperRecordType;
import com.caishi.lkx.exam.ienum.type.QuestionCollectionType;
import com.caishi.lkx.exam.ienum.type.QuestionSourceType;

import com.caishi.lkx.exam.question.QuestionDataProcessComposite;
import com.caishi.lkx.exam.records.RecordsCollectType;
import com.caishi.lkx.exam.records.RecordsGetDataService;
import com.caishi.lkx.exam.records.dto.CollectionErrorAndCollectRecordDataDto;
import com.caishi.lkx.exam.records.dto.QuestionRecordsDto;

import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.caishi.lkx.exam.ienum.type.QuestionCollectionType.chapter;

@Service
public class NoteServiceImpl implements INoteService {
    private final QuestionDataProcessComposite questionDataProcessComposite = QuestionDataProcessComposite.instance;
    @Resource
    private NoteMapper noteMapper;
    @Resource
    private IQuestionService questionService;
    @Resource
    private IChapterService chapterService;

    @Override
    public IBaseMapper<NoteModel, String> getMapper() {
        return noteMapper;
    }

    @Resource
    private IQuestionTypeService questionTypeService;

    @Resource
    private RecordsGetDataService recordsGetDataService;

    @Resource
    private ICategoryService categoryService;
    @Resource
    private IPaperRecordsService paperRecordsService;

    @Resource
    private IPaperService paperService;

    @Override
    public IPage<NoteModel> pageList(Page<NoteModel> pager, String userId, String relationId, String questionId, Integer verify) {
        return noteMapper.pageList(pager, userId, relationId, questionId, verify);
    }

    @Override
    public Map<String, List<QuestionVo>> getNoteQuestionCollection(String relationId, QuestionCollectionType relationName, String userId, Boolean flag, String categoryId) {
        if (flag) {
            NoteModel noteModel = this.getById(relationId);
            RecordsCollectType recordsCollectType;
            if (relationName.equals(QuestionCollectionType.paper)) {
                PaperRecordType recordsModelType;
                PaperRecordsModel recordsModel = paperRecordsService.getById(noteModel.getRelationId());
                if (null != recordsModel) {
                    recordsModelType = recordsModel.getType();
                } else {
                    recordsModelType = PaperRecordType.paperLibrary;
                }

                recordsCollectType = RecordsCollectType.paperRecordType2Type(recordsModelType);
            } else {
                recordsCollectType = RecordsCollectType.collectType2Type(relationName);
            }

            String cid;
            if (recordsCollectType != null) {
                cid = recordsCollectType.staticCid(noteModel.getRelationId());

            } else {
                cid = noteModel.getRelationId();
            }

            CategoryModel category = categoryService.selectOne(Wrappers.<CategoryModel>lambdaQuery().eq(CategoryModel::getId, noteModel.getCategoryId()));
            CollectionErrorAndCollectRecordDataDto collectInCollectDataResult = recordsGetDataService.getCollectInCollectDataResult(userId, category.getIndustryId(), category.getExamId(), category.getId(), recordsCollectType, cid);
            QuestionRecordsDto questionRecordsResult;
            questionRecordsResult = questionRecordsResult(noteModel.getRelationId(), relationName, userId, category);
            QuestionModel question = questionService.getQuestionById(noteModel.getQuestionId());
            QuestionVo vo = this.convertQuestionVo(questionRecordsResult, question);
            vo.setRightAnswer(question.getAnswer());
            Long aLong = collectInCollectDataResult.get(question.getId());
            vo.setCollect(aLong != null);

            String cn = switch (noteModel.getType()) {
                case chapter -> {
                    ChapterModel chapterModel = chapterService.getById(noteModel.getRelationId());
                    if (null == chapterModel) {
                        yield relationName.getDesc();
                    }
                    yield chapterModel.getName();
                }
                case paper -> {
                    PaperModel paperModel = paperService.getById(noteModel.getRelationId());
                    if (ObjectUtil.isNotEmpty(paperModel)) {
                        yield paperModel.getName();
                    } else {
                        PaperRecordsModel paperRecordsModel = paperRecordsService.getById(noteModel.getRelationId());
                        if (null != paperRecordsModel) {
                            yield paperRecordsModel.getName();
                        }
                    }
                    yield relationName.getDesc();
                }
                default -> relationName.getDesc();
            };
            vo.setRecord(questionRecordsResult.get(question.getId()));
            QuestionTypeModel questionTypeModel = questionTypeService.getById(question.getTypeId());
            if (null != questionTypeModel) {
                vo.setType(questionTypeModel.getName());
            } else {
                vo.setType(question.getFirstType().getDesc());
            }
            HashMap<String, List<QuestionVo>> map = new HashMap<>();
            List<QuestionVo> vos = new ArrayList<>();
            vo.setCid(noteModel.getRelationId());
            vo.setCn(cn);
            vo.setSign(questionDataProcessComposite.questionContentSign(question));
            vos.add(vo);
            map.put(vo.getType(), vos);
            return map;
        }

        List<NoteModel> noteModels = this.selectList(Wrappers.<NoteModel>lambdaQuery().eq(NoteModel::getRelationId, relationId).eq(NoteModel::getCreatedBy, userId).eq(StrUtil.isNotBlank(categoryId), NoteModel::getCategoryId, categoryId));
        List<QuestionVo> res = null;
        Map<String, List<QuestionVo>> collect = null;
        CollectionErrorAndCollectRecordDataDto collectMap = null;
        QuestionRecordsDto questionRecordsResult = null;
        if (null != noteModels && !noteModels.isEmpty()) {
            RecordsCollectType recordsCollectType;
            if (relationName.equals(QuestionCollectionType.paper)) {
                PaperRecordsModel recordsModel = paperRecordsService.getById(noteModels.get(0).getRelationId());
                PaperRecordType recordsModelType;
                if (null != recordsModel) {
                    recordsModelType = recordsModel.getType();
                } else {
                    recordsModelType = PaperRecordType.paperLibrary;
                }
                recordsCollectType = RecordsCollectType.paperRecordType2Type(recordsModelType);
            } else {
                recordsCollectType = RecordsCollectType.collectType2Type(relationName);
            }
            String cid;
            if (recordsCollectType != null) {
                cid = recordsCollectType.staticCid(noteModels.get(0).getRelationId());

            } else {
                cid = noteModels.get(0).getRelationId();
            }

            CategoryModel categoryModel = categoryService.selectOne(Wrappers.<CategoryModel>lambdaQuery().eq(CategoryModel::getId, noteModels.get(0).getCategoryId()));
            collectMap = recordsGetDataService.getCollectInCollectDataResult(userId, categoryModel.getIndustryId(), categoryModel.getExamId(), categoryModel.getId(), recordsCollectType, cid);
            questionRecordsResult = questionRecordsResult(relationId, relationName, userId, categoryModel);
        }
        if (relationName == chapter) {//查询章节
            ChapterModel chapterModel = chapterService.selectOne(Wrappers.<ChapterModel>lambdaQuery().eq(ChapterModel::getId, relationId));
            List<NoteModel> models = this.selectList(Wrappers.<NoteModel>lambdaQuery().eq(NoteModel::getCreatedBy, userId).eq(NoteModel::getType, chapter));
            List<QuestionVo> vos = new ArrayList<>();
            List<ChapterModel> list = null;
            String path = chapterModel.getPath();
            String[] split = path.split("/");
            String s = split[0];
            list = chapterService.selectList(Wrappers.<ChapterModel>lambdaQuery().eq(StrUtil.isNotBlank(s), ChapterModel::getParentId, s)
                    .eq(StrUtil.isBlank(s), ChapterModel::getId, chapterModel.getId()));
            //获取章节下面的所有做笔记的题
            this.chapterQuestionList(vos, list, models, relationName, collectMap, questionRecordsResult, relationId);
            collect = vos.stream().collect(Collectors.groupingBy(QuestionVo::getType, Collectors.toList()));
        } else {
            CollectionErrorAndCollectRecordDataDto finalCollectMap = collectMap;
            QuestionRecordsDto finalQuestionRecordsResult = questionRecordsResult;
            res = noteModels.parallelStream().map(n -> setQuestionVo(relationName, relationId, finalCollectMap, finalQuestionRecordsResult, n)).toList();
            collect = res.stream().collect(Collectors.groupingBy(QuestionVo::getType, Collectors.toList()));
        }
        return collect;
    }

    private QuestionRecordsDto questionRecordsResult(String relationId, QuestionCollectionType relationName, String userId, CategoryModel category) {
        QuestionRecordsDto questionRecordsResult;
        RecordsCollectType recordsCollectType;
        if (relationName.equals(QuestionCollectionType.paper)) {
            PaperRecordType recordsModelType;
            PaperRecordsModel recordsModel = paperRecordsService.getById(relationId);
            if (null != recordsModel) {
                recordsModelType = recordsModel.getType();
            } else {
                recordsModelType = PaperRecordType.paperLibrary;
            }
            recordsCollectType = RecordsCollectType.paperRecordType2Type(recordsModelType);
        } else {
            recordsCollectType = RecordsCollectType.collectType2Type(relationName);
        }
        String cid;
        if (recordsCollectType != null) {
            cid = recordsCollectType.staticCid(relationId);

        } else {
            cid = relationId;
        }
        questionRecordsResult = recordsGetDataService.getQuestionRecordsResult(userId, category.getIndustryId(), category.getExamId(), category.getId(), recordsCollectType, cid);
        return questionRecordsResult;
    }

    private QuestionVo convertQuestionVo(QuestionRecordsDto finalQuestionRecordsResult, QuestionModel question) {
        if (question.getSourceType().equals(QuestionSourceType.combination))
            question = questionService.getQuestionById(question.getSourceId());
        question.setChildren(questionService.getCombineList(question.getId()));
        QuestionVo vo = QuestionVo.modelTrans(question);
        vo.setChildren(question.getChildren().stream().map(m -> {
            QuestionVo questionVo = QuestionVo.modelTrans(m);
            questionVo.setRecord(finalQuestionRecordsResult.get(m.getId()));
            questionVo.setType(questionService.questionTypeName(m.getTypeId(), m.getFirstType()));
            return questionVo;
        }).toList());
        return vo;
    }

    private QuestionVo setQuestionVo(QuestionCollectionType relationName, String relationId, CollectionErrorAndCollectRecordDataDto finalCollectMap, QuestionRecordsDto finalQuestionRecordsResult, NoteModel n) {
        QuestionModel question = questionService.getQuestionById(n.getQuestionId());
        QuestionVo vo = this.convertQuestionVo(finalQuestionRecordsResult, question);
        vo.setChildren(question.getChildren().stream().map(QuestionVo::modelTrans).toList());
        vo.setRightAnswer(question.getAnswer());
        Long aLong = finalCollectMap.get(question.getId());
        vo.setCollect(aLong != null);
        vo.setRecord(finalQuestionRecordsResult.get(question.getId()));
        vo.setCid(relationId);
        vo.setCn(relationName.getDesc());
        vo.setSign(questionDataProcessComposite.questionContentSign(question));
        QuestionTypeModel questionTypeModel = questionTypeService.getById(question.getTypeId());
        if (null != questionTypeModel) {
            vo.setType(questionTypeModel.getName());
        } else {
            vo.setType(question.getFirstType().getDesc());
        }
        return vo;
    }

    private void chapterQuestionList(List<QuestionVo> vos, List<ChapterModel> chapterModelList, List<NoteModel> noteModels, QuestionCollectionType relationName, CollectionErrorAndCollectRecordDataDto collectRecordDataDto, QuestionRecordsDto questionRecordsResult, String relationId) {
        if (null != chapterModelList) {
            for (ChapterModel model : chapterModelList) {
                List<NoteModel> list = noteModels.stream().filter(f -> model.getId().equals(f.getRelationId())).toList();
                if (null != list && !list.isEmpty()) {
                    list.forEach(l -> {
                        QuestionVo vo = setQuestionVo(relationName, relationId, collectRecordDataDto, questionRecordsResult, l);
                        vos.add(vo);
                    });
                } else {
                    chapterQuestionList(vos, chapterService.selectList(Wrappers.<ChapterModel>lambdaQuery().eq(ChapterModel::getParentId, model.getId())), noteModels, relationName, collectRecordDataDto, questionRecordsResult, relationId);
                }
            }
        }

    }
    public IPage<NoteModel> getNoteListMy(Page<NoteModel> page, String categoryId, String userId, QuestionCollectionType type){
        IPage<NoteModel> noteListMy = noteMapper.getNoteListMy(page, categoryId, userId, type);
        return noteListMy;
    }
}
